//
//  PSFilterComputerPlaysMisereTests.m
//  PrefCore
//
//  Created by Sergey on 10/3/14.
//  Copyright (c) 2014 Play-on-smart. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "PSFilter.h"
#import "PSFilterUtil.h"
#import "TestHelper.h"

@interface PSFilterTests : XCTestCase
@end

@implementation PSFilterTests

-(void)testComputerPlaysMizereFirstHand {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎7")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♠︎7 ♣︎79JK ♦︎79 ♥︎79T"), 0)
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♥︎7")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♠︎79 ♣︎79JK ♦︎79 ♥︎78"), 0)
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♣︎7")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♠︎79 ♣︎78JK ♦︎78 ♥︎78"), 0)
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♠︎79 ♣︎79JK ♦︎79 ♥︎79")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♠︎79 ♣︎79JK ♦︎79 ♥︎79"), 0)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testComputerPlaysMizereSecondHandHasSuitLower {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎7")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♣︎79JK"), Trick(@"♣︎8"))
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♣︎J")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♣︎79JK"), Trick(@"♣︎Q ♣︎8"))
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♣︎K")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♣︎78JK"), Trick(@"♣︎9 ♣︎A"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testComputerPlaysMizereSecondHandHasSuitHigher {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎89JK")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♣︎89JK"), Trick(@"♣︎7"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testComputerPlaysMizereSecondHandNoSuit {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎7")
    ,   res = PSFilterComputerPlaysMisere(Hand(@"♠︎7 ♣︎79JK ♥︎79TJQ"), Trick(@"♦︎7"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterMissingSuitsAllPresent {
    PSHandHash playerHand = Hand(@"♠︎9TA ♣︎9TQ ♦︎9T ♥︎9T");
    PSHandHash hands[] = {
        Hand(@"♠︎78K ♣︎78 ♦︎78 ♥︎78K")
    ,   playerHand
    ,   Hand(@"♠︎JQ ♣︎KAJ ♦︎JKA ♥︎QA")
    };
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterMissingSuits(playerHand, hands, 1)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterMissingSuitsAllMissing {
    PSHandHash playerHand = Hand(@"♠︎9T ♣︎9T");
    PSHandHash hands[] = {
        Hand(@"♦︎78 ♥︎78")
    ,   playerHand
    ,   Hand(@"♦︎JA ♥︎QA")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎T")
    ,   res = PSFilterMissingSuits(playerHand, hands, 1)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveOpenNoTrumpAnyone {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♦︎7");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎Q ♦︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎J ♦︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterDeclarerFirstHandMoveOpen(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveOpenNoTrumpOpponents {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎7");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎Q ♦︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎J ♦︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎J ♣︎K")
    ,   res = PSFilterDeclarerFirstHandMoveOpen(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveOpenLongTrump {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎79J");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎78Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎JTA ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎J")
    ,   res = PSFilterDeclarerFirstHandMoveOpen(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveOpenShortTrumpLower {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎79");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎7Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎JT ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterDeclarerFirstHandMoveOpen(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveOpenShortTrumpHigher {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎7J");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎78Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎JTA ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎J")
    ,   res = PSFilterDeclarerFirstHandMoveOpen(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveNoTrumpAnyone {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎7J");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎Q ♦︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎J ♦︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎J ♣︎K")
    ,   res = PSFilterDeclarerFirstHandMove(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveNoTrumpOpponents {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎7");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎Q ♦︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎J ♦︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎J ♣︎K")
    ,   res = PSFilterDeclarerFirstHandMove(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveLongTrump {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎79JA");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎789Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎9T ♣︎JTA ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎A")
    ,   res = PSFilterDeclarerFirstHandMove(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveShortTrumpLower {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎79");
    PSHandHash hands[] = {
        Hand(@"♠︎A ♣︎7Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎T ♣︎JT ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterDeclarerFirstHandMove(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterDeclarerFirstHandMoveVeryLongTrump {
    PSHandHash playerHand = Hand(@"♠︎J ♣︎K ♥︎7JQKA");
    PSHandHash hands[] = {
        Hand(@"♠︎A789 ♣︎78Q ♥︎8")
    ,   playerHand
    ,   Hand(@"♠︎TQK ♣︎9JTA ♥︎T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎A")
    ,   res = PSFilterDeclarerFirstHandMove(playerHand, kSuitHearts, 1, hands)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereFirstHand {
    PSHandHash playerHand = Hand(@"♠︎A789 ♣︎78Q ♦︎9T ♥︎8");
    PSHandHash hands[] = {
        playerHand
    ,   Hand(@"♠︎J ♣︎K ♦︎78J ♥︎7JQKA")
    ,   Hand(@"♠︎TQK ♣︎9JTA ♦︎K ♥︎9T")
    };
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   playerHand
        ,   1 // PlayerId
        ,   0 // Trick
        ,   0 // Round
        ,   0 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereSecondHandEarlyRoundNoTakeSecond {
    PSHandHash hands[] = {
        Hand(@"♠︎789 ♣︎78JK ♦︎79")
    ,   Hand(@"♠︎TJ ♣︎9A ♦︎8TQK ♥︎TJ")
    ,   Hand(@"♠︎KQA ♣︎TQ ♦︎JA ♥︎89A")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎TJ")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♥︎TJ")
        ,   1 // PlayerId
        ,   Trick(@"♥︎7")
        ,   0 // Round
        ,   1 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereSecondHandEarlyRoundNoTakeThird {
    PSHandHash hands[] = {
        Hand(@"♠︎789 ♣︎78JK ♦︎79")
    ,   Hand(@"♠︎TJ ♣︎9A ♦︎8TQK ♥︎7T")
    ,   Hand(@"♠︎KQA ♣︎TQ ♦︎JA ♥︎9JA")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎7T")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♥︎7T")
        ,   1 // PlayerId
        ,   Trick(@"♥︎8")
        ,   0 // Round
        ,   1 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereSecondHandEarlyRoundTake {
    PSHandHash hands[] = {
        Hand(@"♠︎789 ♣︎78JK ♦︎79")
    ,   Hand(@"♠︎TJ ♣︎9A ♦︎8TQK ♥︎7T")
    ,   Hand(@"♠︎KQA ♣︎TQ ♦︎JA ♥︎8JA")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎7")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♥︎7T")
        ,   1 // PlayerId
        ,   Trick(@"♥︎9")
        ,   0 // Round
        ,   1 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereSecondHandLateRound {
    PSHandHash hands[] = {
        Hand(@"♠︎J ♣︎K ♦︎78J ♥︎7JQ")
    ,   Hand(@"♠︎A789 ♣︎78Q ♦︎9")
    ,   Hand(@"♠︎TQK ♣︎9JTA")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎9")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♦︎9")
        ,   1 // PlayerId
        ,   Trick(@"♦︎K")
        ,   2 // Round
        ,   1 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereThirdHandEarlyRoundNoTake {
    PSHandHash hands[] = {
        Hand(@"♠︎789 ♣︎78JK ♦︎79")
    ,   Hand(@"♠︎KQA ♣︎TQ ♦︎JA ♥︎89")
    ,   Hand(@"♠︎TJ ♣︎9A ♦︎8TQK ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎TJ")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♥︎TJ")
        ,   2 // PlayerId
        ,   Trick(@"♥︎7A")
        ,   0 // Round
        ,   2 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereThirdHandEarlyRoundTake {
    PSHandHash hands[] = {
        Hand(@"♠︎789 ♣︎78JK ♦︎79")
    ,   Hand(@"♠︎KQA ♣︎TQ ♦︎JA ♥︎8JA")
    ,   Hand(@"♠︎TJ ♣︎9A ♦︎8TQK ♥︎7T")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎7")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♥︎7T")
        ,   2 // PlayerId
        ,   Trick(@"♥︎9 ♥︎8")
        ,   0 // Round
        ,   2 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterHumanPlaysMisereThirdHandLateRound {
    PSHandHash hands[] = {
        Hand(@"♠︎J ♣︎K ♦︎78J ♥︎7JQ")
    ,   Hand(@"♠︎TQK ♣︎9JTA")
    ,   Hand(@"♠︎A789 ♣︎78Q ♦︎9")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎9")
    ,   res = PSFilterHumanPlaysMisere(
            [PSEvaluator evaluatorForType:kEvaluatorMisere]
        ,   Hand(@"♦︎9")
        ,   2 // PlayerId
        ,   Trick(@"♦︎K")
        ,   2 // Round
        ,   2 // handIndex
        ,   hands
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterPlayerNonFirstHandMovePossibleTrickHigherCard {
    PSHandHash playerHand = Hand(@"♦︎9TJ");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterPlayerNonFirstHandMove(playerHand, 1, Trick(@"♦︎8"), kSuitHearts, 1)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterPlayerNonFirstHandMovePossibleTrickWithTrump {
    PSHandHash playerHand = Hand(@"♦︎9");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterPlayerNonFirstHandMove(playerHand, 1, Trick(@"♥︎A"), kSuitDiamonds, 1)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterPlayerNonFirstHandMoveNoTrick {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎7")
    ,   res = PSFilterPlayerNonFirstHandMove(Hand(@"♣︎78Q"), 1, Trick(@"♣︎A"), kSuitDiamonds, 1)
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testLowestCandidates {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♠︎7 ♣︎7 ♦︎7 ♥︎7")
    ,   res = PSFilterGetLowestCandidates(Hand(@"♠︎78K ♣︎78 ♦︎78 ♥︎78K"))
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♠︎A ♣︎A ♦︎A ♥︎A")
    ,   res = PSFilterGetLowestCandidates(Hand(@"♠︎A ♣︎A ♦︎A ♥︎A"))
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♠︎7 ♣︎K ♦︎T ♥︎7")
    ,   res = PSFilterGetLowestCandidates(Hand(@"♠︎78K ♣︎KA ♦︎TA ♥︎78K"))
    ,   @"Got %@", PSHandDescription(res)
    );
    XCTAssertEqual(
        Hand(@"♣︎7 ♥︎7")
    ,   res = PSFilterGetLowestCandidates(Hand(@"♣︎78 ♥︎78K"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterSecondKingPlusMarriage {
    PSHandHash playerHand = Hand(@"♠︎78 ♣︎9TJQ ♦︎8 ♥︎79A");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterSecondPlusKingTrick(playerHand, 1, playerHand, 2, Hand(@"♠︎A ♣︎8A ♦︎79TJA ♥︎QK"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterSecondKingPlusTriliage {
    PSHandHash playerHand = Hand(@"♠︎78 ♣︎9TJQ ♦︎8 ♥︎79A");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterSecondPlusKingTrick(playerHand, 1, playerHand, 2, Hand(@"♠︎A ♣︎A ♦︎79TJA ♥︎JQK"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterSecondKingPlusMarriageWithCoverFirstHandHasAce {
    PSHandHash playerHand = Hand(@"♠︎78 ♣︎9TJQ ♦︎8 ♥︎79A");
    PSHandHash res;
    XCTAssertEqual(
        PSHandRemoveSuit(playerHand, kSuitHearts)
    ,   res = PSFilterSecondPlusKingTrick(playerHand, 1, playerHand, 2, Hand(@"♠︎A ♣︎A ♦︎79TJA ♥︎TQK"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterSecondKingPlusMarriageWithCoverFirstHandNoAce {
    PSHandHash playerHand = Hand(@"♠︎78 ♣︎9TJQ ♦︎8 ♥︎789");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterSecondPlusKingTrick(playerHand, 1, playerHand, 2, Hand(@"♠︎A ♣︎A ♦︎79TJA ♥︎TQK"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterSecondKingPlusInThreeSuits {
    PSHandHash playerHand = Hand(@"♠︎8A ♣︎9TJA ♦︎8 ♥︎78A");
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎8")
    ,   res = PSFilterSecondPlusKingTrick(playerHand, 1, playerHand, 2, Hand(@"♠︎7K ♣︎7K ♦︎9TJA ♥︎7K"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterThirdQueenNoThreeCards {
    PSHandHash playerHand = Hand(@"♠︎8A ♣︎9TJA ♦︎8 ♥︎78A");
    PSHandHash res;
    XCTAssertEqual(
        playerHand
    ,   res = PSFilterThirdQueenTrick(playerHand, Hand(@"♠︎7K ♣︎7K ♦︎9TJA ♥︎7K"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterThirdQueenOneSuit {
    PSHandHash playerHand = Hand(@"♠︎8A ♣︎9TJA ♦︎8 ♥︎78A");
    PSHandHash res;
    XCTAssertEqual(
        PSHandRemoveSuit(playerHand, kSuitClubs)
    ,   res = PSFilterThirdQueenTrick(playerHand, Hand(@"♠︎7K ♣︎78Q ♦︎7QK ♥︎79K"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterThirdQueenTwoSuits {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎8 ♥︎78A")
    ,   res = PSFilterThirdQueenTrick(Hand(@"♠︎8A ♣︎9TJA ♦︎8 ♥︎78A"), Hand(@"♠︎79Q ♣︎78Q ♦︎9QK ♥︎7K"))
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveSecondNoBeatingCard {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎9")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎9TJK")
        ,   1 // PlayerId
        ,   Trick(@"♣︎A")
        ,   kSuitDiamonds
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveSecondWithBeatingCard {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎J")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎9JK")
        ,   1 // PlayerId
        ,   Trick(@"♣︎T")
        ,   kSuitDiamonds
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveSecondWithBeatingCardTrump {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎9")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎9J")
        ,   1 // PlayerId
        ,   Trick(@"♥︎A")
        ,   kSuitClubs
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveLastNoBeatingCard {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎9")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,  Hand(@"♣︎9J")
        ,  2 // PlayerId
        ,  Trick(@"♣︎K ♣︎Q")
        ,  kSuitDiamonds
        ,  2 // Hand index
        ,  0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveLastWithMyBeatingCard {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎Q")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,  Hand(@"♣︎9TQ")
        ,  2 // PlayerId
        ,  Trick(@"♣︎J ♣︎7")
        ,  kSuitDiamonds
        ,  2 // Hand index
        ,  0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveLastWithMyBeatingCardTrump {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎8")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,  Hand(@"♦︎89A")
        ,  2 // PlayerId
        ,  Trick(@"♣︎A ♣︎7")
        ,  kSuitDiamonds
        ,  2 // Hand index
        ,  0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveLastWithMyBeatingCardBothTrumps {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♦︎9")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,  Hand(@"♦︎79A")
        ,  2 // PlayerId
        ,  Trick(@"♦︎8 ♣︎7")
        ,  kSuitDiamonds
        ,  2 // Hand index
        ,  0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveLastWithPartnersBeatingCard {
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎9")
    ,   res = PSFilterWhisterAfterDeclarerMove(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,  Hand(@"♣︎9TQ")
        ,  2 // PlayerId
        ,  Trick(@"♣︎7 ♣︎J")
        ,  kSuitHearts
        ,  2 // Hand index
        ,  0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenSecondNoBeatingCard {
    PSHandHash hands[] = {
        Hand(@"♠︎QA ♣︎7A ♦︎78TQA ♥︎9")
    ,   Hand(@"♠︎78JK ♣︎9K ♦︎J ♥︎QKA")
    ,   Hand(@"♠︎9T ♣︎8TJQ ♦︎9K ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎9")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎9K")
        ,   hands
        ,   1 // PlayerId
        ,   Trick(@"♣︎A")
        ,   kSuitDiamonds
        ,   0 // round
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenSecondBeatingCardPartner {
    PSHandHash hands[] = {
        Hand(@"♠︎QA ♣︎9A ♦︎78TQA ♥︎9")
    ,   Hand(@"♠︎78JK ♣︎7K ♦︎J ♥︎QKA")
    ,   Hand(@"♠︎9T ♣︎8TJQ ♦︎9K ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎7")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎7K")
        ,   hands
        ,   1 // PlayerId
        ,   Trick(@"♣︎9")
        ,   kSuitDiamonds
        ,   0 // round
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenSecondWithBeatingCard {
    PSHandHash hands[] = {
        Hand(@"♠︎QA ♣︎9A ♦︎78TQA ♥︎9")
    ,   Hand(@"♠︎78JK ♣︎7K ♦︎J ♥︎QKA")
    ,   Hand(@"♠︎9T ♣︎8TJQ ♦︎9K ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎Q")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♥︎QKA")
        ,   hands
        ,   1 // PlayerId
        ,   Trick(@"♥︎9")
        ,   kSuitDiamonds
        ,   0 // round
        ,   1 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenLastNoBeatingCard {
    PSHandHash hands[] = {
        Hand(@"♠︎QA ♣︎7A ♦︎78TQA ♥︎9")
    ,   Hand(@"♠︎78JK ♣︎9K ♦︎J ♥︎QKA")
    ,   Hand(@"♠︎9T ♣︎8TJQ ♦︎9K ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♣︎8")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♣︎8TJQ")
        ,   hands
        ,   2 // PlayerId
        ,   Trick(@"♣︎A ♣︎9")
        ,   kSuitDiamonds
        ,   0 // round
        ,   2 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenLastBeatingCardPartner {
    PSHandHash hands[] = {
        Hand(@"♠︎QA ♣︎9A ♦︎78TQA ♥︎9")
    ,   Hand(@"♠︎78JK ♣︎7K ♦︎J ♥︎QKA")
    ,   Hand(@"♠︎9T ♣︎8TJQ ♦︎9K ♥︎TJ")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎T")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♥︎TJ")
        ,   hands
        ,   2 // PlayerId
        ,   Trick(@"♥︎9 ♥︎Q")
        ,   kSuitDiamonds
        ,   0 // round
        ,   2 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

-(void)testFilterWhisterAfterDeclarerMoveOpenLastWithBeatingCard {
    PSHandHash hands[] = {
        Hand(@"♠︎79 ♣︎8A ♦︎78TQA")
    ,   Hand(@"♠︎8 ♣︎7K ♦︎J9K ♥︎QKA")
    ,   Hand(@"♠︎TJQKA ♣︎9TJQ ♥︎J")
    };
    PSHandHash res;
    XCTAssertEqual(
        Hand(@"♥︎J")
    ,   res = PSFilterWhisterAfterDeclarerMoveOpen(
            [PSEvaluator evaluatorForType:kEvaluatorTricking]
        ,   Hand(@"♠︎TJQKA ♣︎9TJQ ♥︎J")
        ,   hands
        ,   2 // PlayerId
        ,   Trick(@"♥︎9 ♥︎7")
        ,   kSuitDiamonds
        ,   0 // round
        ,   2 // Hand index
        ,   0 // Declarer
        )
    ,   @"Got %@", PSHandDescription(res)
    );
}

@end

